﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Server.Service.Model;
using Server.Controller;
using System.ServiceModel;

namespace Server.Service
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    class PlanRouteService : IPlanRouteService
    {
        public WCFUser Login(string email, string password)
        {
            WCFUser sendUser;
            using (Server.DB.Context db = new Server.DB.Context())
            {
                //Run Controller
                Server.Controller.LoginController loginCtr = new Controller.LoginController(db);
                Server.Model.User user = null;
                try
                {
                    user = loginCtr.Login(email, password);
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("Could not login:" + email);
                    throw new FaultException(e.Message);
                }
                //Create WCF Models
                sendUser = createClientUser(user);
            }
            return sendUser;
        }

        public ICollection<WCFStation> GetAllStations()
        {
            List<WCFStation> allStations = new List<WCFStation>();
            using (DB.Context db = new DB.Context())
            {
                //Run Controller
                Controller.PlanRouteController prCtr = new Controller.PlanRouteController(db);
                List<Server.Model.Station> stations = (List<Server.Model.Station>)prCtr.GetAllStations();
                
                //Create WCF models
                foreach (Server.Model.Station station in stations)
                {
                    allStations.Add(new WCFStation(station));
                }
            } 
            return allStations;
        }

        public ICollection<WCFStation> PlanRoute(WCFStation start, WCFStation end, DateTime date, WCFCarModel carModel)
        {
            //Create empty list
            List<WCFStation> allStations = new List<WCFStation>();
            
            //Setting the cntext
            using (Server.DB.Context db = new Server.DB.Context())
            {
                //Create entity models
                Server.Model.Station eStart = db.Stations.Find(start.Id);
                Server.Model.Station eEnd = db.Stations.Find(end.Id);
                Server.Model.CarModel eCarModel = db.CarModels.Find(carModel.Id);

                //Initiate controller
                PlanRouteController prCtr = new PlanRouteController(db);

                ICollection<Server.Model.Station> stations = new List<Server.Model.Station>();
                try
                {
                    stations = prCtr.PlanRoute(eStart, eEnd, date, eCarModel, eCarModel.BatteryType);
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("Could not create route between " + start.Id + " and " + end.Id);
                    throw new FaultException(e.Message);
                }
                foreach (Server.Model.Station station in stations)
                {
                    allStations.Add(new WCFStation(station));
                }
            }
            return allStations;
        }


        public WCFReservation ConfirmRoute(WCFUser user, WCFCar car, ICollection<WCFStation> stations, DateTime date)
        {
            WCFReservation res;
            using (Server.DB.Context db = new Server.DB.Context())
            {
                Server.Model.User nUser = db.Users.Find(user.Id);
                Server.Model.Car nCar = db.Cars.Find(car.Id);
                List<Server.Model.Station> nStations = new List<Server.Model.Station>();
                foreach (WCFStation station in stations)
                {
                    Server.Model.Station s = db.Stations.Find(station.Id);
                    nStations.Add(s);
                }

                PlanRouteController prCtr = new PlanRouteController(db);
                Server.Model.Reservation nReservation = null;
                try
                {
                    nReservation = prCtr.ComfirmRoute(nUser, nCar, nStations, date);
                }
                catch (Exception e)
                {
                    throw new FaultException(e.Message);
                }
                res = new WCFReservation(nReservation);

                //foreach (Server.Model.PartReservation pr in nReservation.PartReservations)
                //{
                //    res.PartReservations.Add(new WCFPartReservation(pr));
                //}
            }

            return res;
        }


        public ICollection<WCFReservation> GetActiveReservationsByUserDate(WCFUser user, DateTime date)
        {
            //Create empty list
            List<WCFReservation> allReservations = new List<WCFReservation>();

            //Setting the context
            using (Server.DB.Context db = new Server.DB.Context())
            {
                //Create entity models
                Server.Model.User eUser = db.Users.Find(user.Id);
                
                //Initiate controller
                ReservationController resCtr = new ReservationController(db);
                
                ICollection<Server.Model.Reservation> reservations = new List<Server.Model.Reservation>();

                reservations = resCtr.GetActiveReservationsByUserDate(eUser, date);
                //Console.WriteLine("Reservations fetched");
                foreach (Server.Model.Reservation r in reservations)
                {
                    WCFReservation res1 = new WCFReservation(r);
                    foreach (Server.Model.PartReservation pr in r.PartReservations)
                    {
                        WCFPartReservation partRes = new WCFPartReservation(pr);
                        partRes.Station = new WCFStation(pr.Station);
                        res1.PartReservations.Add(partRes);
                    }
                    res1.Car = new WCFCar(r.Car);
                    res1.Car.CarModel = new WCFCarModel(r.Car.CarModel);

                    allReservations.Add(res1);
                }
            }
            //Console.WriteLine("Reservations fetched");
            return allReservations;
        }


        public WCFUser updateUser(WCFUser user)
        {
            WCFUser newUser;
            using (Server.DB.Context db = new Server.DB.Context())
            {
                #region Create model
                //Create Entity model
                Server.Model.User eUser = db.Users.Find(user.Id);
                eUser.AddressLine1 = user.AddressLine1;
                eUser.AddressLine2 = user.AddressLine2;
                eUser.Name = user.Name;
                eUser.Phone = user.Phone;
                Server.Model.ZipCodeCity newZip = db.ZipCodeCity.Find(user.ZipCodeCity.ZipCode);
                if (newZip == null)
                {
                    throw new FaultException("Kunne ikke finde postnummer!");
                }
                eUser.ZipCodeCity = newZip;
                #endregion

                #region Call Controller
                //Call controller;
                UserController uCtr = new UserController(db);
                eUser = uCtr.UpdateUser(eUser);
                #endregion

                #region Return variable
                //Create return variable
                newUser = createClientUser(eUser);
                #endregion

            }
            return newUser;
        }

        private WCFUser createClientUser(Server.Model.User user)
        {
            WCFUser sendUser = new WCFUser(user);
            foreach (Server.Model.Car car in user.Cars)
            {
                WCFCar car1 = new WCFCar(car);
                car1.CarModel = new WCFCarModel(car.CarModel);
                sendUser.Cars.Add(car1);
            }
            return sendUser;

        }
    }
}
